#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <ctime>

#pragma comment(lib, "Ws2_32.lib")

#define DEFAULT_PORT "27015"
#define CONNECT_TRIES 10

struct addrinfo *result = NULL, *ptr = NULL, hints;

//client
void delay(int n)
{
    time_t start_time, cur_time;

    time(&start_time);
    do
    {
    time(&cur_time);
    }
    while((cur_time - start_time) < n);
}

int main(void)
{
    printf("Hallo wereld! Ik ben een client, waar de fuck is mijn server?\n");

    WSADATA wsaData;

    int iResult, counter;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        getchar(); return 1;
    }

    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo("127.0.0.1", DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed: %d\n", iResult);
        WSACleanup();
        getchar(); return 1;
    }

    SOCKET ConnectSocket = INVALID_SOCKET;

    // Attempt to connect to the first address returned by
    // the call to getaddrinfo
    ptr=result;

    // Create a SOCKET for connecting to server
    ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Error at socket(): %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        getchar(); return 1;
    }

    bool failed;
    // Connect to server.
    for(int i = 0; i < CONNECT_TRIES; i++)
    {
        iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            printf("Unable to connect to server!\n");
            failed = true;
        }else{
            failed = false;
            break;
        }
        delay(2); // moet nog gefixed worden/beter (#include <windows.h> with Sleep(milliseconds)?)
    }

    // Should really try the next address returned by getaddrinfo
    // if the connect call failed
    // But for this simple example we just free the resources
    // returned by getaddrinfo and print an error message

    freeaddrinfo(result);

    if (failed) {
        ConnectSocket = INVALID_SOCKET;
        closesocket(ConnectSocket);
        WSACleanup();
        getchar(); return 1;
    }

    /** sending shizzle **/

    #define DEFAULT_BUFLEN 512

    int recvbuflen = DEFAULT_BUFLEN;

    char sendbuf[512] = "";
    char recvbuf[DEFAULT_BUFLEN];

    do
    {
        counter = 0;
        printf("> ");
        do
        {
            sendbuf[counter++] = getchar();
        }while(sendbuf[counter-1] != '\n');
        sendbuf[counter-1] = '\0';
        // Send an initial buffer
        iResult = send(ConnectSocket, sendbuf, (int) strlen(sendbuf), 0);
        if (iResult == SOCKET_ERROR) {
            printf("send failed: %d\n", WSAGetLastError());
            closesocket(ConnectSocket);
            WSACleanup();
            return 1;
        }
    }while (strcmp(sendbuf, "exit") != 0);

    printf("Bytes Sent: %ld\n", iResult);

    // shutdown the connection for sending since no more data will be sent
    // the client can still use the ConnectSocket for receiving data
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 1;
    }

    // Receive data until the server closes the connection
    do {
        iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
        if (iResult > 0)
            printf("Bytes received: %d\n", iResult);
        else if (iResult == 0)
            printf("Connection closed\n");
        else
            printf("recv failed: %d\n", WSAGetLastError());
    } while (iResult > 0);

    /** einde sending shizzle **/

    printf("succesfull so far, yay!");
    getchar();
}